<template>
  <div class="check-card-wrapper">
    <div
      v-for="item in options"
      :key="item.value"
      class="check-card"
      :class="{
        'is-checked': isCheckedItem(item.value),
        'is-disabled': currentDisabled || item.disabled,
        [`is-${currentSize}`]: !!currentSize,
      }"
      @click="handleClick(item)"
    >
      <div class="check-card__header">
        <div v-if="$slots.cover || item.cover" class="check-card__cover">
          <slot name="cover">
            <img v-if="item.cover" :src="item.cover" :item="item" />
          </slot>
        </div>
        <div class="check-card__content">
          <div class="check-card__title">
            <slot name="title">{{ item.label }}</slot>
          </div>
          <div v-if="$slots.desc || item.desc" :title="item.desc" class="check-card__description">
            <slot name="desc" :item="item">{{ item.desc }}</slot>
          </div>
        </div>
      </div>
      <div v-if="$slots.extra || item.extra" class="check-card__extra">
        <slot name="extra" :item="item">{{ item.extra }}</slot>
      </div>
      <div v-if="isCheckedItem(item.value)" class="check-card__check">
        <el-icon v-if="isCheckedItem(item.value)"><Check /></el-icon>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { useFormSize, useFormDisabled, useSize } from 'element-plus';
import type { CheckCardOptionItem, CheckCardValueType, CheckCardModelValue, CheckCardSize } from './types';

defineOptions({ name: 'CheckCard' });

const modelValue = defineModel<CheckCardModelValue>({ default: '' });
const label = defineModel('label', { default: '' });

const props = defineProps({
  options: {
    type: Array as PropType<CheckCardOptionItem[]>,
    default: () => [],
  },
  extra: { type: String, default: '' },
  disabled: { type: Boolean, default: false },
  multiple: { type: Boolean, default: false },
  size: { type: String as PropType<CheckCardSize>, default: '' },
});

const emit = defineEmits(['change']);

const formDisabled = useFormDisabled(props.disabled);
const formSize = useFormSize();
const globalSize = useSize();

const currentSize = computed(() => globalSize.value || formSize.value || props.size);
const currentDisabled = computed(() => formDisabled.value || props.disabled);

const isCheckedItem = (value: CheckCardValueType) => {
  if (!props.multiple) {
    return modelValue.value === value;
  }
  const values = modelValue.value as CheckCardValueType[];
  return values.includes(value);
};

const handleClick = (item: CheckCardOptionItem) => {
  if (currentDisabled.value || item.disabled) return;
  if (item.value === modelValue.value) return;
  if (!props.multiple) {
    modelValue.value = item.value;
    label.value = item.label;
    emit('change', modelValue.value);
    return;
  }
  const values = modelValue.value as CheckCardValueType[];
  const index = values.indexOf(item.value);
  if (index !== -1) {
    values.splice(index, 1);
  } else {
    values.push(item.value);
  }
  label.value = values.map((v) => props.options.find((o) => o.value === v)?.label).join(', ') ?? '';
  emit('change', modelValue.value);
};
</script>

<style scoped lang="scss">
.check-card-wrapper {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;

  .check-card {
    position: relative;
    width: 250px;
    padding: 12px 14px;
    overflow: hidden;
    cursor: pointer;
    background-color: var(--el-bg-color);
    border: 1px solid var(--el-border-color);
    border-radius: calc(var(--border-radius) - 4px);
    transition: all 0.25s;

    &:hover:not(.is-disabled) {
      border-color: var(--el-color-primary);
    }

    &.is-checked {
      background-color: rgba(var(--el-color-primary-rgb), 0.1);
      border-color: var(--el-color-primary);
    }

    &.is-disabled {
      cursor: not-allowed;
      background-color: var(--el-disabled-bg-color);
      opacity: 0.7;
    }

    &.is-large {
      width: 300px;
      padding: 16px 18px;
    }

    &.is-small {
      width: 200px;
      padding: 10px 12px;
    }

    &__header {
      display: flex;
      gap: 12px;
    }

    &__cover {
      flex-shrink: 0;
      width: 48px;
      height: 48px;
      overflow: hidden;
      border-radius: calc(var(--border-radius) - 4px);

      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
    }

    &__content {
      flex: 1;
      min-width: 0;
    }

    &__title {
      margin-bottom: 4px;
      overflow: hidden;
      text-overflow: ellipsis;
      font-weight: 500;
      white-space: nowrap;
    }

    &__description {
      display: -webkit-box;
      overflow: hidden;
      text-overflow: ellipsis;
      -webkit-line-clamp: 2;
      font-size: 12px;
      line-height: 1.3;
      color: var(--el-text-color-secondary);
      -webkit-box-orient: vertical;
    }

    &__extra {
      font-size: 12px;
      line-height: 1.5;
      color: var(--el-text-color-secondary);
    }

    &__check {
      position: absolute;
      top: 0;
      right: 0;
      display: flex;
      align-items: flex-start;
      justify-content: flex-end;
      width: 0;
      height: 0;
      color: white;
      border-top: 20px solid var(--el-color-primary);
      border-left: 20px solid transparent;

      .el-icon {
        position: absolute;
        top: -20px;
        right: 1px;
        font-size: 12px;
      }
    }
  }
}
</style>
